﻿//Unity4.6中定义在基类中的拥有ContextMenu属性的方法在子类上右键调用会失败
//这应该是更新后的一个BUG，暂时使用这个方法来解决下
#define CONTEXT_MENU_BUG_WORKAROUND
using UnityEngine;
using System.Collections.Generic;
#if UNITY_EDITOR
    using UnityEditor;

 #endif
using System.Collections;
using System;
public class UIPrefabPool : UISelectObjectPath {
    List<GameObject> spawnObjects;
    GameObject spawnOneObject;
    public delegate void HideSurplusSpawnItemHandler(Transform item,bool active);
    public HideSurplusSpawnItemHandler hideSurplusSpawnItemHandler;
    public delegate void SpawnCallback(int index, bool finishAll);     //生成后的回调，参数是list下标
    /// <summary>
    ///  获得一定数量的对象
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="count"></param>
    /// <param name="spawnList"></param>
    public void SetSpawnCount<T>(int count,ref List<T> spawnList) where T:Component
    {
        spawnList.Clear();
        if (null == spawnObjects)
            spawnObjects = new List<GameObject>();
        if (null != spawnOneObject && !spawnObjects.Contains(spawnOneObject)) spawnObjects.Add(spawnOneObject);
        int haveItemCount = spawnObjects.Count;
        int subNum = haveItemCount - count;
        if(subNum<0)
        {
            List<GameObject> gos = SpawnObjects(-subNum);
            for (int g = 0; g < -subNum; g++)
            {
                spawnObjects.Add(gos[g]);
            }
        }
        int nowHaveItemCount = spawnObjects.Count;
        GameObject spawnGo;
        for (int i = 0; i < nowHaveItemCount; i++)
        {
            spawnGo = spawnObjects[i];
            if (i < count)
            {
                spawnList.Add(spawnGo.GetComponent(typeof(T)) as T);
                SurplusSpawnItem(spawnGo, true);
                //NGUITools.SetActive(spawnGo, true);
            }
            else
                SurplusSpawnItem(spawnGo, false);
        }
    }

    void SurplusSpawnItem(GameObject go, bool active)
    {
        if (null != hideSurplusSpawnItemHandler)
            hideSurplusSpawnItemHandler(go.transform, active);
        else
            NGUITools.SetActive(go, active);
    }
    /// <summary>
    ///  获得一定数量的对象
    ///  目前仅热更新可用.
    /// </summary>
    public void SetSpawnCountForHotfix<T>(int count, ref List<T> spawnList) where T : Component
    {
        spawnList.Clear();
        if (null == spawnObjects)
            spawnObjects = new List<GameObject>();
        if (null != spawnOneObject &&!spawnObjects.Contains(spawnOneObject))spawnObjects.Add(spawnOneObject);

        int haveItemCount = spawnObjects.Count;
        int subNum = haveItemCount - count;
        if (subNum < 0)
        {
            List<GameObject> gos = SpawnObjects(-subNum);
            for (int g = 0; g < -subNum; g++)
            {
                spawnObjects.Add(gos[g]);
            }
        }
        int nowHaveItemCount = spawnObjects.Count;
        GameObject spawnGo;
        for (int i = 0; i < nowHaveItemCount; i++)
        {
            spawnGo = spawnObjects[i];
            if (i < count)
            {
                spawnList.Add(spawnGo.GetComponent(typeof(T)) as T);
                SurplusSpawnItem(spawnGo, true);
            }
            else
                SurplusSpawnItem(spawnGo, false);
        }
    }
    public ArrayList SetSpawnCount(int count,Type t)
    {
        ArrayList spawnList = new ArrayList();
        if (null == spawnObjects)
            spawnObjects = new List<GameObject>();
        if (null != spawnOneObject) spawnObjects.Add(spawnOneObject);
        int haveItemCount = spawnObjects.Count;
        int subNum = haveItemCount - count;
        for (int g = 0; g < -subNum; g++)
        {
            spawnObjects.Add(SpawnOneObject((haveItemCount + g).ToString()));
        }
        int nowHaveItemCount = spawnObjects.Count;
        GameObject spawnGo;
        for (int i = 0; i < nowHaveItemCount; i++)
        {
            spawnGo = spawnObjects[i];
            if (i < count)
            {
                spawnList.Add(spawnGo.GetComponent(t));
                SurplusSpawnItem(spawnGo, true);
                //NGUITools.ImmediatelyCreateDrawCalls(spawnGo);
                //NGUITools.ImmediatelyCreateRectDrawCalls(spawnGo);
            }
            else
                SurplusSpawnItem(spawnGo, false);
        }
        return spawnList;
    }


    /// <summary>
    /// 异步创建prefab
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="count"></param>
    /// <param name="spawnList"></param>
    /// <param name="unitPerFrame">每帧生成几个单位，小于等于0时会被设定为1</param>
    /// <param name="cb"></param>
    /// <returns></returns>
    public IEnumerator<T> SetSpawnCountAsync<T>(int count, List<T> spawnList, float unitPerFrame, SpawnCallback cb = null) where T : Component
    {
        if (unitPerFrame <= 0)
            unitPerFrame = 1;
        if (count == spawnList.Count)
        {
            if (null != cb)
            {
                for (int i = 0; i < count; i++)
                    cb(i, i == count - 1);
            }
            yield break;
        }
        spawnList.Clear();
        if (null == spawnObjects)
            spawnObjects = new List<GameObject>();
        if (null != spawnOneObject) spawnObjects.Add(spawnOneObject);
        GameObject spawnGo;
        yield return null;
        float currentMaxUnit = unitPerFrame;         //当前帧应该加载到第几个单位
        for (int i = 0; i < count;)
        {
            if (i >= spawnObjects.Count)
            {
                spawnObjects.Add(SpawnOneObject(i.ToString()));
            }
            spawnGo = spawnObjects[i];
            if (i < count)
            {
                spawnList.Add(spawnGo.GetComponent(typeof(T)) as T);
                SurplusSpawnItem(spawnGo, true);
            }
            else
                SurplusSpawnItem(spawnGo, false);
            if (cb != null)
                cb(i, i+1 >= count);
            //按速率自增
            if (i + 1 < count)
            {
                if (i + 1 < currentMaxUnit)
                    ++i;
                else
                {
                    float delta = 0;
                    while (Mathf.FloorToInt(currentMaxUnit + delta) <= Mathf.FloorToInt(currentMaxUnit))
                    {
                        yield return null;
                        delta += unitPerFrame;
                    }
                    currentMaxUnit += delta;
                    ++i;
                }
            }
            else
                ++i;
        }
    }
    /// <summary>
    /// 获得一个对象
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <returns></returns>
    public T SetSpawnCount<T>() where T : Component
    {
        if (null == spawnObjects)
        {
            if (null != spawnOneObject)
                return spawnOneObject.GetComponent<T>();
            else
            {
                spawnOneObject = SpawnOneObject("0");
                if(null!= spawnOneObject)
                    return spawnOneObject.GetComponent<T>();
                else
                {
                    return null;
                }
            }
        }
        else
        {
            int haveItemCount = spawnObjects.Count;
            if (haveItemCount == 0)
            {
                spawnOneObject = SpawnOneObject("0");
                if (null != spawnOneObject)
                    return spawnOneObject.GetComponent<T>();
                else
                {
                    return null;
                }
            }
            else
            {
                GameObject spawnGo;
                for (int i = 0; i < haveItemCount; i++)
                {
                    spawnGo = spawnObjects[i];
                    if (i < 1)
                    {
                        spawnOneObject = spawnGo;
                        SurplusSpawnItem(spawnGo, true);
                    }
                    else
                        SurplusSpawnItem(spawnGo, false);
                }
                return spawnOneObject.GetComponent<T>();
            }
        }
    }
    /// <summary>
    /// 获得一个对象
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <returns></returns>
    public Component SetSpawnCount( Type t )
    {
        if (null == spawnObjects)
        {
            if (null != spawnOneObject)
                return spawnOneObject.GetComponent(t);
            else
            {
                spawnOneObject = SpawnOneObject("0");
                return spawnOneObject.GetComponent(t);
            }
        }
        else
        {
            int haveItemCount = spawnObjects.Count;
            if (haveItemCount == 0)
            {
                spawnOneObject = SpawnOneObject("0");
                return spawnOneObject.GetComponent(t);
            }
            else
            {
                GameObject spawnGo;
                for (int i = 0; i < haveItemCount; i++)
                {
                    spawnGo = spawnObjects[i];
                    if (i < 1)
                    {
                        spawnOneObject = spawnGo;
                        SurplusSpawnItem(spawnGo, true);
                    }
                    else
                        SurplusSpawnItem(spawnGo, false);
                }
                return spawnOneObject.GetComponent(t);
            }
        }
    }


    public GameObject SetSpawnCount()
    {
        if (null == spawnObjects)
        {
            if (null != spawnOneObject)
                return spawnOneObject;
            else
            {
                spawnOneObject = SpawnOneObject("0");
                return spawnOneObject;
            }
        }
        else
        {
            int haveItemCount = spawnObjects.Count;
            if (haveItemCount == 0)
            {
                spawnOneObject = SpawnOneObject("0");
                return spawnOneObject;
            }
            else
            {
                GameObject spawnGo;
                for (int i = 0; i < haveItemCount; i++)
                {
                    spawnGo = spawnObjects[i];
                    if (i < 1)
                    {
                        spawnOneObject = spawnGo;
                        SurplusSpawnItem(spawnGo, true);
                    }
                    else
                        SurplusSpawnItem(spawnGo, false);
                }
                return spawnOneObject;
            }
        }
    }
    /// <summary>
    /// 获得当前实例过的所有对象
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="allSpawnList"></param>
    public void GetAllSpawnList<T>(ref List<T> allSpawnList) where T:Component
    {
        if (null == spawnObjects) return;
        int count = spawnObjects.Count;
        if (count == allSpawnList.Count) return;
        allSpawnList.Clear();
        for (int i = 0; i < count; i++)
            allSpawnList.Add(spawnObjects[i].GetComponent(typeof(T)) as T);
    }
    public override string GetkeyFilterPath()
    {
        return base.GetkeyFilterPath();
    }
    public override bool IsOpenABLoader()
    {
        return false;
    }
    public override void Clear()
    {
        base.Clear();
        if (null != spawnObjects)
            spawnObjects.Clear();
        spawnOneObject = null;
    }
}
